<!-- 聊天面板 -->
<template>
  <div class="chat-panel">
    <div class="chat-panel__title" v-if="selectMember">
      <span class="title">{{
        selectMember.nickName ? selectMember.nickName : selectMember.name
      }}</span>
      <!-- 群聊内的展示用户列表的按钮 -->
      <div
        v-if="isGroup"
        class="chat-panel__title__group"
        v-click-outside="handleClose"
      >
        <i class="tico tico-daohanglan-lianxiren" @click="handleOpen"> </i>
        <GuroSetting v-if="groupMembersVisible" />
      </div>
    </div>
    <!-- 展示聊天内容的地方 -->
    <div :start-index="start" :on-data-change="onHeaderDataChange"></div>
    <div class="chat-panel__content" ref="main">
      <!-- 加载历史消息 -->
      <div
        v-show="roomId !== '100008'"
        class="load-more-msg"
        @click="getHistoryList"
      >
        <i v-show="getHistoryMsgLoading" class="el-icon-loading"></i>
        {{ historyMsgLoadComplete ? "没有更多了" : "加载更多" }}
      </div>
      <div
        v-for="(item, index) in selectChatList"
        :id="index"
        :key="item.backId + item.isTemp + item.subType"
      >
        <Chat :priorInfo="selectChatList[index - 1]" :info="item" :id="index" />
      </div>

      <!-- <virtual-list
        :size="size"
        :remain="remain"
        :start="start"
        :itemprops="getItemProps"
        :itemcount="selectChatList.length"
        :item="item"
        :scrollelement="scrollelement"
      /> -->
    </div>
    <!-- 编辑发送信息的地方 -->
    <div
      v-if="
        !(
          groupState === 'openGroupForbidSpeak' ||
          groupState === 'openUserForbidSpeak' ||
          groupState === 'dissolved'
        )
      "
      class="chat-panel__edit"
      @dragenter="dropPreventDefault"
      @dragover="dropPreventDefault"
      @drop="dodrop"
    >
      <div class="chat-panel__edit__title">
        <el-tooltip
          :open-delay="1000"
          effect="dark"
          content="表情"
          placement="top-start"
        >
          <div v-click-outside="hideDialogEmoji">
            <i class="tico tico-smile icon" @click="showDialogEmoji" />
            <div class="emoji">
              <div class="emoji__body" :hidden="dialogHidden">
                <VEmojiPicker
                  :pack="pack"
                  labelSearch
                  @select="onSelectEmoji"
                />
              </div>
            </div>
          </div>
        </el-tooltip>
        <el-tooltip
          :open-delay="1000"
          effect="dark"
          content="图片"
          placement="top-start"
        >
          <i
            class="tico tico-shurukuang-tupianicon icon"
            @click="selectFile('imgupload')"
          />
        </el-tooltip>
        <el-tooltip
          :open-delay="1000"
          effect="dark"
          content="文件"
          placement="top-start"
        >
          <i
            class="tico tico-shurukuang-wenjianicon icon"
            @click="selectFile('fileupload')"
          />
        </el-tooltip>
        <el-tooltip
          :open-delay="1000"
          effect="dark"
          content="视频"
          placement="top-start"
        >
          <i class="tico tico-vedeo- icon" @click="selectFile('videoupload')" />
        </el-tooltip>
        <!-- <el-tooltip
          :open-delay="1000"
          effect="dark"
          content="临时"
          placement="top-start"
        >
          <i class="tico tico-vedeo- icon" @click="toggleSendMsgModelShow(true)" />
        </el-tooltip> -->
      </div>
      <!-- 艾特功能 -->
      <div ref="wrap" @input="handleInput" @keydown="handleKeyDown">
        <div class="chat-panel__list" :style="style" v-if="atwho">
          <ul class="list__ul">
            <li
              class="mention-name"
              v-for="(item, index) in atwho.list"
              :key="index"
              :class="isCur(index) && 'atwho-cur'"
              :ref="isCur(index) && 'cur'"
              :data-index="index"
              @mouseenter="handleItemHover"
              @click="handleItemClick"
            >
              <img
                :src="item.avatar"
                alt=""
                class="img-style"
                v-if="item.avatar"
              />
              <span class="img-default img-style" v-else></span>
              <span class="name" v-text="item.name"></span>
            </li>
          </ul>
        </div>
        <Input
          class="chat-panel__edit__input"
          type="textarea"
          autofocus
          id="mousePostion"
          placeholder="回车发送信息，ctrl+回车换行"
          v-model="content"
        />
      </div>
    </div>
    <!-- 禁言中、群解散的编辑区域 -->
    <div v-else class="chat-panel__edit-disable">
      {{
        groupState === "openGroupForbidSpeak" ||
        groupState === "openUserForbidSpeak"
          ? "禁言中"
          : ""
      }}
    </div>

    <input id="fileupload" type="file" @change="handleFile($event)" />
    <input
      id="videoupload"
      type="file"
      accept="video/*"
      @change="handleFile($event)"
    />
    <input
      id="imgupload"
      type="file"
      @change="handleFile($event)"
      accept="image/*"
    />
    <TranspondModel />
    <SendMsgModel
      :sendMsgModelShow="sendMsgModelShow"
      :receiver="chatObjectInfo"
      :dragFileList="dragFileList"
      v-on:onToggleSendMsgModelShow="toggleSendMsgModelShow"
      v-on:onConfirmSend="handleDropFile"
    />
    <!-- :dragFileList='dragFileList' -->
  </div>
</template>

<script>
import _ from 'lodash'
import { getStorage } from '../../../js/utils'
// import moment from 'moment'
import getCaretCoordinates from 'textarea-caret'
import { mapState } from 'vuex'
import Chat from './chatCard/index'
import SendMsgModel from './SendMsgModel'
import VEmojiPicker from 'v-emoji-picker'
import packData from 'v-emoji-picker/data/emojis.json'
import { Input } from 'element-ui'
import Jindouyun from '../../../utils/jindouyun'
import { blobToFile, dataURLtoBlob } from '../../../utils/utils'
import TranspondModel from './TranspondModel'
import GuroSetting from './GuroSetting'
import vClickOutside from 'v-click-outside'
import { sendSingleChatText, sendGroupChatVideo, sendSingleChatVideo, sendGroupChatFile, sendGroupleChatImage,
  sendGroupChatText, sendSingleChatImage, sendSingleChatFile, sendGroupChatAt } from '../../../api/ChatSocket.js'
import { GetSingleHistoryList, UpdateSingleReceiver } from '../../../api/Single'
import { UpdateGroupReceiver, getGroupHistoryList } from '../../../api/Group'
import BigNumber from 'bignumber.js'
import { uuid } from 'vue-uuid'

// import VirtualList from 'vue-virtual-scroll-list'
const _jindouyun = new Jindouyun({
  // userId: '1111434885161394177',
  userId: '1111435842045702146',
  header: {},
  token: ''
})
const msgTypeMap = {
  'imgupload': 1,
  'fileupload': 2,
  'videoupload': 3
}
export default {
  components: { GuroSetting, VEmojiPicker, Input, TranspondModel, Chat, SendMsgModel },
  props: {
    value: { // 输入框初始值
      type: String,
      default: null
    },
    suffix: { // 插入字符链接
      type: String,
      default: ' '
    },
    loop: { // 上下箭头循环
      type: Boolean,
      default: true
    },
    avoidEmail: { // @前不能是字符
      type: Boolean,
      default: true
    },
    hoverSelect: { // 悬浮选中
      type: Boolean,
      default: true
    },
    nameKey: {
      type: String,
      default: ''
    }
  },
  data () {
    return {
      scrollelement: null,
      remain: 10,
      start: 0,
      size: 40,
      item: Chat,
      dialogHidden: true, // emoji选择面板开关
      pack: packData.data, // emoji的列表（这个时框架提供的不用管）
      content: '', // 聊天框输入的文本
      msgType: 0, // 0文本, 1图片, 2文件, 3视频
      groupMembersVisible: false, // 群聊用户列表开关
      cursor: 0,
      leftstyle: '15px',
      atItems: ['@'],
      bindsValue: this.value != null,
      atwho: null,
      canBeEdited: false,
      insertAtArr: [],
      sendMsgModelShow: false,
      dragFileList: {}, // 拖拽的文件列表
      historyMsgLoadComplete: false, // 漫游消息是否拉取完
      getHistoryMsgLoading: false,
      onSetMsgReceiver: false, // 改变消息已接受状态
      disableScroll: false // 禁止窗口滚动
    }
  },
  computed: {
    ...mapState('app', ['selectMember', 'chatList', 'roomId', 'groupList', 'chatRoomInfo', 'friendList', 'chatListBase']),
    selectChatList: function () {
      // 选中的聊天列表
      let data = []
      if (this.chatList[this.roomId]) {
        data = this.chatList[this.roomId]
      }
      return data
    },
    isGroup: function () {
      // 是否群聊
      const i = _.findIndex(this.groupList, e => e.roomId + '' === this.roomId)
      return i !== -1
    },
    chatObjectInfo: function () {
      let obj = {}
      if (this.isGroup) {
        obj = this.groupList.find(i => i.roomId + '' === this.roomId)
      } else {
        obj = this.friendList.find(i => i.roomId + '' === this.roomId)
      }
      return obj || {}
    },
    members: function () {
      if (this.isGroup) {
        const temp = _.cloneDeep(this.chatRoomInfo[this.roomId].data)
        return _.remove(temp, e => !e.delFlag)
      } else {
        return null
      }
    },
    groupState: function () {
      const obj = this.groupList.find(i => i.roomId === this.roomId)
      if (obj) {
        return obj.groupState || ''
      } else if (this.selectChatList[0] && this.selectChatList[0].msgType === 'groupChat') {
        return 'dissolved'
      } else {
        return ''
      }
    },
    style () {
      if (this.atwho) {
        const {
          // list,
          // cur,
          x,
          y
        } = this.atwho
        const {
          wrap
        } = this.$refs
        const el = this.$el.querySelector('textarea')
        if (wrap) {
          const left = x + el.offsetLeft - el.scrollLeft + 'px'
          const top = y + el.offsetTop - el.scrollTop + 25 + 'px'
          return {
            left,
            top
          }
        }
      }
      return null
    }
  },
  watch: {
    // selectChatList: {
    //   handler (newdata) {
    //     var content = document.getElementById('content')
    //     content.scrollTop = content.scrollHeight
    //   },
    //   deep: true
    // },
    // 实时监听光标的位置
    // members () {
    //   this.handleInput(true)
    // },
    value (value, oldValue) {
      if (this.bindsValue) {
        this.handleValueUpdate(value)
      }
    },
    roomId (value, oldValue) {
      // 当前的房间文本消息先保存草稿，
      // 再从新聊天室读取文本消息，同时置空聊天室消息（用于侧边消息【草稿】的显隐）
      const content = this.content
      const insertAtArr = this.insertAtArr
      const parameter = {
        roomId: oldValue,
        content
      }
      if (insertAtArr && insertAtArr.length !== 0) {
        parameter.insertAtArr = insertAtArr
      }
      this.$store.commit('app/SETCHATLISTBASE', parameter)

      const currentBase = this.chatListBase[value]
      if (currentBase) {
        const { content, insertAtArr, someoneAtMe } = currentBase
        this.content = content
        this.insertAtArr = insertAtArr || []
        const resetParame = {
          roomId: value,
          content: '',
          insertAtArr: []
        }
        someoneAtMe && (resetParame.someoneAtMe = false)
        this.$store.commit('app/SETCHATLISTBASE', resetParame)
      } else {
        this.content = ''
        this.insertAtArr = []
      }

      // 重置拉取历史按钮，拉取历史数据
      this.$data.getHistoryMsgLoading = false
      this.$data.historyMsgLoadComplete = false
      if (this.selectChatList.length < 20 && this.roomId !== '100008') {
        this.getHistoryList()
      }
    },
    async selectChatList (newVal) {
      // '修改消息已接受状态'
      if (this.$data.onSetMsgReceiver || newVal.length === 0 || this.roomId === '100008') return
      this.$data.onSetMsgReceiver = true
      const unreadMsgIds = []
      newVal.forEach(item => {
        if (item.unread) {
          unreadMsgIds.push(item.messageId)
        }
      })

      if (unreadMsgIds.length > 0) {
        console.log('修改已接受状态')

        let res

        if (this.isGroup || newVal[0].msgType === 'groupChat') {
          res = await UpdateGroupReceiver({
            ids: unreadMsgIds
          })
        } else {
          res = await UpdateSingleReceiver({
            ids: unreadMsgIds
          })
        }
        if (res.status === 200) {
          this.$store.commit('app/SET_MSG_RECEIVER', {
            roomId: this.roomId,
            unreadMsgIds
          })
        }
      }
      this.$data.onSetMsgReceiver = false
    },
    'selectChatList.length' (nVal) {
      if (this.scrollelement && !this.$data.disableScroll) {
        this.$nextTick(() => {
          this.scrollelement.scrollTop = this.scrollelement.scrollHeight
        })
      }
      this.$data.disableScroll && (this.$data.disableScroll = false)
    }
  },
  // updated () {
  //   console.log('更新了', this.$data.disableScroll)
  //   if (this.scrollelement) {
  //     setTimeout(() => {
  //       this.scrollelement.scrollTop = this.scrollelement.scrollHeight - this.scrollelement.clientHeight
  //     }, 10)
  //   }
  // },

  mounted () {
    this.scrollelement = this.$refs.main

    const self = this
    this.$nextTick(function () {
      /**
       * 描述
       * @author lin
       * @date 2020-03-16
       * @param {dom} e
       * @returns
       */
      document.onkeydown = function (e) {
        // 原生实现回车发送, shift+回车换行
        if (e.keyCode === 13 && e.ctrlKey) {
          e.preventDefault()
          self.lineFeed()
          self.$nextTick(() => {
            document.getElementById('mousePostion').scrollTop = document.getElementById('mousePostion').scrollHeight
          })
        } else if (e.keyCode === 13 && !e.ctrlKey) {
          e.preventDefault()
          self.send()
        }
      }
    })
    // 获取光标的位置
    if (this.bindsValue) {
      this.handleValueUpdate(this.value)
    }

    // // 黏贴文件功能
    // const testArea = document.getElementById('mousePostion')
    // testArea && testArea.addEventListener('paste', function (event) {
    //   // 获取clipboardData对象
    //   // let obj = (event.clipboardData || window.clipboardData)
    //   // let text = obj.getData('text')
    //   // console.log(obj)
    //   // console.log(obj.files)
    //   // console.log(obj.items)
    //   // console.log(text)
    // })
  },
  directives: {
    clickOutside: vClickOutside.directive
  },
  methods: {
    // 拖拽文件发送消息
    dropPreventDefault (event) {
      event.stopPropagation()
      event.preventDefault()
    },
    toggleSendMsgModelShow (val) {
      this.sendMsgModelShow = val
    },
    setSendMsgModelShow (val) {
      this.sendMsgModelShow = val
    },
    dodrop (event) {
      event.stopPropagation()
      event.preventDefault()
      let dt = event.dataTransfer
      this.dragFileList = dt.files
      this.setSendMsgModelShow(true)
    },
    /**
     * 描述
     * @author lin
     * @date 2020-03-16
     * @param {string} type
     * @param {string} value
     * @returns
     */
    onHeaderDataChange (type, value) {
      if (type === 'start') {
        this.start = value
      }
    },
    getItemProps (itemIndex) {
      return {
        key: itemIndex,
        props: {
          height: this.size,
          index: itemIndex,
          priorInfo: this.selectChatList[itemIndex - 1],
          info: this.selectChatList[itemIndex],
          id: itemIndex
        }
      }
    },
    // 艾特功能mousePostion
    getAtAndIndex (text, ats) {
      return ats.map((at) => {
        return {
          at,
          index: text.lastIndexOf(at)
        }
      }).reduce((a, b) => {
        return a.index > b.index ? a : b
      })
    },
    isCur (index) {
      return index === this.atwho.cur
    },
    handleValueUpdate (value) { // 更新textarea的值
      const el = this.$el.querySelector('textarea')
      if (value !== el.value) {
        el.value = value
      }
    },
    handleItemHover (e) {
      if (this.hoverSelect) {
        this.selectByMouse(e)
      }
    },
    handleItemClick (e) {
      this.selectByMouse(e)
      this.insertItem()
    },

    handleKeyDown (e) {
      const {
        atwho
      } = this
      if (atwho) {
        if (e.keyCode === 38 || e.keyCode === 40) { // ↑/↓
          if (!(e.metaKey || e.ctrlKey)) {
            e.preventDefault()
            e.stopPropagation()
            this.selectByKeyboard(e)
          }
          return
        }
        if (e.keyCode === 13) { // enter
          this.insertItem()
          e.preventDefault()
          e.stopPropagation()
          return
        }
        if (e.keyCode === 27) { // esc
          this.closePanel()
          return
        }
      }
      // 为了兼容ie ie9~11 editable无input事件 只能靠keydown触发 textarea正常 ??不愧是甜丽大佬，学习了学习了
      // 另 ie9 textarea的delete不触发input
      // eslint-disable-next-line
      const isValid = e.keyCode >= 48 && e.keyCode <= 90 || e.keyCode === 8
      if (isValid) {
        setTimeout(() => {
          this.handleInput()
        }, 50)
      }
      if (e.keyCode === 8) { // 删除
        // this.handleDelete(e)
      }
      if (e.keyCode === 13) { // 删除
        this.$emit('enterSend', e)
      }
    },
    handleInput (event) {
      const el = this.$el.querySelector('textarea')
      this.$emit('input', el.value) // 更新父组件
      const text = el.value.slice(0, el.selectionEnd)
      if (text && this.isGroup) {
        const {
          atItems,
          avoidEmail
        } = this
        let show = true
        const {
          at,
          index
        } = this.getAtAndIndex(text, atItems)
        if (index < 0) show = false
        const prev = text[index - 1] // 上一个字符
        const chunk = text.slice(index + at.length, text.length)
        if (avoidEmail) { // 上一个字符不能为字母数字 避免与邮箱冲突，微信则是避免 所有字母数字及半角符号
          if (/^[a-z0-9]$/i.test(prev)) show = false
        }

        if (/^\s/.test(chunk)) show = false // chunk以空白字符开头不匹配 避免`@ `也匹配
        if (!show) {
          this.closePanel()
        } else {
          const {
            members
            // filterMatch
          } = this
          if (!event) { // fixme: should be consistent with At.vue
            this.$emit('at', chunk)
          }
          const data = [
            {
              name: '所有人'
            }
          ]
          const membersNew = [ ...data, ...members ]
          const isMeNameId = getStorage('aillo_id') ? getStorage('aillo_id') : getStorage('aillo_name')
          _.remove(membersNew, e => e.userId + '' === isMeNameId)
          const matched = membersNew.filter(v => {
            return v.toString().indexOf(chunk) > -1
          })
          if (matched.length) {
            this.openPanel(matched, chunk, index, at)
          } else {
            this.closePanel()
          }
        }
      } else {
        this.closePanel()
      }
    },

    closePanel () {
      if (this.atwho) {
        this.atwho = null
      }
    },
    openPanel (list, chunk, offset, at) { // 打开Atuser列表  matched, chunk, index, at  过滤数组，匹配项，匹配项index，'@'
      const fn = () => {
        const el = this.$el.querySelector('textarea')
        const atEnd = offset + at.length // 从@后第一位开始
        const rect = getCaretCoordinates(el, atEnd)
        this.atwho = {
          chunk,
          offset,
          list,
          atEnd,
          x: rect.left,
          y: rect.top - 4,
          cur: 0 // todo: 尽可能记录
        }
      }
      if (this.atwho) {
        fn()
      } else { // 焦点超出了显示区域 需要提供延时以移动指针 再计算位置
        setTimeout(fn, 10)
      }
    },

    selectByMouse (e) {
      function closest (el, predicate) { // 遍历直到有data-index为止
        do {
          if (predicate(el)) return el
        } while (el = el && el.parentNode)
      }

      const el = closest(e.target, d => {
        return d.getAttribute('data-index')
      })

      const cur = +el.getAttribute('data-index')

      this.atwho = {
        ...this.atwho,
        cur
      }
    },
    selectByKeyboard (e) {
      const offset = e.keyCode === 38 ? -1 : 1
      const {
        cur,
        list
      } = this.atwho
      const nextCur = this.loop
        ? (cur + offset + list.length) % list.length
        : Math.max(0, Math.min(cur + offset, list.length - 1))
      this.atwho = {
        ...this.atwho,
        cur: nextCur
      }
    },
    setInsertAtArr (item) {
      const { userId, name } = item
      this.insertAtArr.push({ userId, userName: name })
    },
    insertStr (soure, start, newStr) {
      return soure.slice(0, start) + newStr + soure.slice(start)
    },
    // todo: 抽离成库并测试
    insertText (text, el) {
      const inputObj = document.getElementById('mousePostion')
      this.content = this.insertStr(this.content, inputObj.selectionStart, text)
      // this.content += text
      const start = el.selectionStart
      const end = el.selectionEnd
      el.value = el.value.slice(0, start) +
      text + el.value.slice(end)
      const newEnd = start + text.length
      el.selectionStart = newEnd
      el.selectionEnd = newEnd
    },
    insertItem () {
      const {
        list,
        cur,
        atEnd
      } = this.atwho
      const {
        suffix,
        atItems
      } = this
      const el = this.$el.querySelector('textarea')
      const text = el.value.slice(0, atEnd)
      const {
        at,
        index
      } = this.getAtAndIndex(text, atItems)
      const start = index + at.length // 从@后第一位开始
      el.selectionStart = start
      el.focus() // textarea必须focus回来
      const curItem = list[cur].name
      const t = '' + curItem + suffix

      this.setInsertAtArr(list[cur])
      this.insertText(t, el)
      // this.$emit('insert', curItem) // 插入字符
      this.handleInput()
    },
    handleClose () {
      // 关闭群聊用户列表
      this.groupMembersVisible = false
    },
    hideDialogEmoji (e) {
      // 关闭表情包
      this.dialogHidden = true
    },
    /** 开关Emoji选择窗口 */
    showDialogEmoji () {
      this.dialogHidden = !this.dialogHidden
    },
    handleOpen () {
      // 开关群聊用户列表
      if (this.groupState === 'dissolved' || this.groupState === 'delGroupMember') return
      this.groupMembersVisible = !this.groupMembersVisible
    },
    // 触发文件选择
    selectFile (type) {
      this.msgType = msgTypeMap[type]
      document.getElementById(type).click()
    },
    // 拖拽文件遍历，根据类型分别发送出去
    handleDropFile (e) {
      const temp = []
      for (let i = 0; i < e.length; i++) {
        const type = e[i].type.split('/')[0]
        switch (type) {
          case 'image':
            temp.push(this.asyncimgupload(e[i], i))
            break
          case 'video':
            temp.push(this.asyncvideoUpload(e[i], i))
            break
          default:
            temp.push(this.asyncfileUpload(e[i], i))
        }
      }
      // Promise.all(
      //   temp
      // ).then(result => {
      //   e.target.value = ''
      // })
    },
    // 文件遍历，根据类型分别发送出去
    handleFile (e) {
      const temp = []
      for (let i = 0; i < e.target.files.length; i++) {
        const type = e.target.files[i].type.split('/')[0]
        switch (type) {
          case 'image':
            temp.push(this.asyncimgupload(e.target.files[i], i))
            break
          case 'video':
            temp.push(this.asyncvideoUpload(e.target.files[i], i))
            break
          default:
            temp.push(this.asyncfileUpload(e.target.files[i], i))
        }
      }
      Promise.all(
        temp
      ).then(result => {
        e.target.value = ''
      })
    },
    asyncvideoUpload (theFile, i) {
      if (theFile.size > 100 * 1024 * 1024) {
        this.$message({
          message: '您的文件/视频过大，请发送小于100M的文件/视频',
          type: 'warning'
        })
        return
      }
      return new Promise((resolve, reject) => {
        let height = 0
        let width = 0
        let duration = 0
        const requestId = uuid.v1()
        const that = this
        const video = document.createElement('video')
        const source = document.createElement('source')
        const url = URL.createObjectURL(theFile)
        const type = theFile.type
        source.src = url
        source.type = type
        video.appendChild(source)
        video.currentTime = 0.1
        video.addEventListener('canplay', function () {
          // 获取视频大小
          width = this.videoWidth
          height = this.videoHeight
          duration = Math.round(this.duration)
        })
        video.addEventListener('loadeddata', function () {
          const canvas = document.createElement('canvas')
          const roomId = _.cloneDeep(that.roomId)
          setTimeout(async () => {
            canvas.width = width
            canvas.height = height
            canvas
              .getContext('2d')
              .drawImage(video, 0, 0, canvas.width, canvas.height)
            const imgsrc = canvas.toDataURL('image/png')
            const blobData = dataURLtoBlob(imgsrc)
            const imgFile = blobToFile(blobData, '首页图片.png')
            let tempVideo
            if (_.isUndefined(that.selectMember.isEncryptGroup)) {
              tempVideo = {
                msgType: 'singleChat',
                subType: 'video',
                isEncrypted: 0,
                fileName: theFile.name,
                fileSize: theFile.size,
                width,
                height,
                videoUrl: url,
                roomId: roomId,
                frameUrl: imgsrc,
                duration: 0,
                backId: requestId,
                requestId,
                timestamp: BigNumber(new Date().getTime()).toString(),
                isTemp: true,
                megState: that.groupState === 'delGroupMember' ? 2 : 1,
                isMe: true
              }
            } else {
              tempVideo = {
                msgType: 'groupChat',
                subType: 'video',
                isEncrypted: 0,
                receiverId: that.selectMember.id + '',
                fileName: theFile.name,
                fileSize: theFile.size,
                width,
                height,
                roomId: roomId,
                videoUrl: url,
                frameUrl: imgsrc,
                duration: 0,
                requestId,
                backId: requestId,
                timestamp: BigNumber(new Date().getTime()).toString(),
                isTemp: true,
                megState: that.groupState === 'delGroupMember' ? 2 : 1,
                isMe: true
              }
            }
            if (roomId !== '100008') {
              if (that.isGroup) {
                tempVideo.msgType = 'groupChat'
                tempVideo.sendId = sessionStorage.getItem('aillo_id')
                tempVideo.recediveId = _.cloneDeep(that.roomId)
              } else {
                tempVideo.msgType = 'singleChat'
                tempVideo.sendId = sessionStorage.getItem('aillo_id')
                tempVideo.recediveId = that.selectMember.id + ''
              }
            } else {
              // 文件助手
              tempVideo.msgType = 'fileHelper'
            }
            that.$store.dispatch('app/addChatListMsg', tempVideo) // 把视频信息存入聊天列表
            if (that.groupState === 'delGroupMember') { // 被移出群，不得发送消息
              return
            }
            const videoRes = await _jindouyun.upload({ file: theFile, isPublic: false })
            const imgRes = await _jindouyun.upload({ file: imgFile, isPublic: false })
            const imgUrl = _jindouyun.getDownloadUrl(imgRes.data.data) // 获取第一帧截图
            const videoFile = {
              fileName: theFile.name,
              fileSize: theFile.size,
              width,
              height,
              frameUrl: imgUrl
            }
            let sendData
            if (_.isUndefined(that.selectMember.isEncryptGroup)) { // 发送单聊信息或群聊信息
              sendData = sendSingleChatVideo(videoRes.data.data.id,
                roomId, that.selectMember.id + '', videoFile, duration,
                requestId, tempVideo.sendId, tempVideo.recediveId)
            } else {
              sendData = sendGroupChatVideo(videoRes.data.data.id,
                roomId, videoFile, duration,
                requestId, tempVideo.sendId, tempVideo.recediveId)
            }
            const _sendData = { ...sendData, ...sendData.data }
            _sendData.isMe = true
            _sendData.isTemp = true
            delete _sendData.data

            console.log('_sendData', _sendData)
            that.$store.commit('app/AFTEROFUPLOAD', _sendData)
            resolve()
          }, 1000)
        })
      })
    },
    /**
     * 文件上传的方法
     * @param e (input获取的文件对象)
     */
    // fileUpload (e) {
    //   const temp = []
    //   for (let i = 0; i < e.target.files.length; i++) {
    //     temp.push(this.asyncfileUpload(e, i))
    //   }
    //   Promise.all(
    //     temp
    //   ).then(result => {
    //     e.target.value = ''
    //   })
    // },
    asyncfileUpload (theFile, i) {
      if (theFile.size > 100 * 1024 * 1024) {
        this.$message({
          message: '您的文件/视频过大，请发送小于100M的文件/视频',
          type: 'warning'
        })
        return
      }
      return new Promise((resolve, reject) => {
        const requestId = uuid.v1()
        let data = {
          subType: 'file',
          requestId,
          isEncrypted: 0,
          receiverId: this.selectMember.id + '',
          roomId: _.cloneDeep(this.roomId),
          backId: requestId,
          fileName: theFile.name,
          fileSize: theFile.size,
          timestamp: BigNumber(new Date().getTime()).toString(),
          isMe: true,
          isTemp: true,
          megState: this.groupState === 'delGroupMember' ? 2 : 1,
          tempUrl: URL.createObjectURL(theFile),
          sendId: sessionStorage.getItem('aillo_id')
        }
        if (this.roomId !== '100008') {
          if (this.isGroup) {
            data.msgType = 'groupChat'
            data.recediveId = _.cloneDeep(this.roomId)
          } else {
            data.msgType = 'singleChat'
            data.recediveId = this.selectMember.id + ''
          }
        } else {
          // 文件助手
          data.msgType = 'fileHelper'
        }

        this.$store.dispatch('app/addChatListMsg', data) // 把文件信息存入聊天列表
        if (this.groupState === 'delGroupMember') { // 被移出群，不得发送消息
          return
        }

        const that = this
        const roomId = _.cloneDeep(that.roomId)
        let sendData
        _jindouyun.upload({ file: theFile, isPublic: true }).then(a => { // 文件上传
          if (_.isUndefined(this.selectMember.isEncryptGroup)) { // 单聊
            sendData = sendSingleChatFile(a.data.data.id, roomId, that.selectMember.id + '',
              { fileName: a.data.data.fileName, fileSize: a.data.data.fileSize },
              requestId, data.sendId, data.recediveId)
          } else {
            sendData = sendGroupChatFile(a.data.data.id, roomId,
              { fileName: a.data.data.fileName, fileSize: a.data.data.fileSize },
              requestId, data.sendId, data.recediveId)
          }
          const _sendData = { ...sendData, ...sendData.data }
          _sendData.isMe = true
          _sendData.isTemp = true
          delete _sendData.data
          this.$store.commit('app/AFTEROFUPLOAD', _sendData)
          resolve()
        })
      })
    },
    /**
     * 图片上传的方法
     * @param e (input获取的文件对象)
     */
    // imgUpload (e) {
    //   const temp = []
    //   for (let i = 0; i < e.target.files.length; i++) {
    //     temp.push(this.asyncimgupload(e, i))
    //   }
    //   Promise.all(
    //     temp
    //   ).then(result => {
    //     e.target.value = ''
    //   })
    // },
    asyncimgupload (theFile, i) {
      if (theFile.size > 100 * 1024 * 1024) {
        this.$message({
          message: '您的文件/视频过大，请发送小于100M的文件/视频',
          type: 'warning'
        })
        return
      }
      const that = this
      const roomId = _.cloneDeep(that.roomId)
      return new Promise((resolve, reject) => {
        const img = document.createElement('img')
        let requestId = uuid.v1()
        img.src = URL.createObjectURL(theFile)
        img.onload = () => {
          let imgData = {
            subType: 'image',
            requestId,
            isEncrypted: 0,
            receiverId: that.selectMember.id + '',
            fileName: theFile.name,
            backId: requestId,
            fileSize: theFile.size,
            width: img.width,
            height: img.height,
            roomId,
            tempImg: URL.createObjectURL(theFile),
            timestamp: BigNumber(new Date().getTime()).toString(),
            sendId: sessionStorage.getItem('aillo_id'),
            megState: that.groupState === 'delGroupMember' ? 2 : 1
          }
          if (roomId !== '100008') {
            if (this.isGroup) {
              imgData.msgType = 'groupChat'
              imgData.recediveId = _.cloneDeep(this.roomId)
            } else {
              imgData.msgType = 'singleChat'
              imgData.recediveId = this.selectMember.id + ''
            }
          } else {
            // 文件助手
            imgData.msgType = 'fileHelper'
          }
          imgData.isMe = true
          imgData.isTemp = true
          this.$store.dispatch('app/addChatListMsg', imgData)
        }
        if (this.groupState === 'delGroupMember') { // 被移出群，不得发送消息
          return
        }
        let data = { sendId: sessionStorage.getItem('aillo_id') }
        if (this.isGroup) {
          data.recediveId = _.cloneDeep(this.roomId)
        } else {
          data.recediveId = this.selectMember.id + ''
        }
        // ↑缓存的本地数据
        _jindouyun.uploadImg({ file: theFile, isPublic: true }).then(a => { // 上传图片
          // let sendData
          if (_.isUndefined(this.selectMember.isEncryptGroup)) { // 单聊
            sendSingleChatImage(a.data.data.id, roomId, that.selectMember.id + '',
              { fileName: a.data.data.fileName, fileSize: a.data.data.fileSize, width: a.data.data.width, height: a.data.data.height },
              requestId, data.sendId, data.recediveId)
          } else { // 群聊
            sendGroupleChatImage(a.data.data.id, roomId,
              { fileName: a.data.data.fileName, fileSize: a.data.data.fileSize, width: a.data.data.width, height: a.data.data.height },
              requestId, data.sendId, data.recediveId)
          }
          resolve()
        })
      })
    },
    processeAtData () {
      const myId = sessionStorage.getItem('aillo_id')
      const all = this.insertAtArr.find(i => (i.userName === '所有人' && !i.userId))
      if (all) {
        const members = this.chatRoomInfo[this.roomId].data
        const othermembers = members.filter(i => (i.userId + '' !== myId && i.delFlag !== true))

        return othermembers.map(function (i) {
          return { userId: i.userId, userName: i.name }
        })
      }
      return this.insertAtArr.filter(i => {
        const str = '@' + i.userName
        return this.content.includes(str)
      })
    },
    send () {
      if (this.content.trim() !== '') {
        const requestId = uuid.v1()
        const roomId = _.cloneDeep(this.roomId)
        const insertAtArr = this.processeAtData()
        let temp = {
          subType: 'text',
          requestId,
          isEncrypted: 0,
          msg: this.content,
          backId: requestId,
          timestamp: BigNumber(new Date().getTime()).toString(),
          isTemp: true,
          megState: this.groupState === 'delGroupMember' ? 2 : 1,
          isMe: true,
          roomId
        }
        insertAtArr.length > 0 && (temp.atModelList = insertAtArr)

        temp.msgType = 'singleChat'
        this.isGroup && (temp.msgType = 'groupChat')
        roomId === '100008' && (temp.msgType = 'fileHelper')

        this.$store.dispatch('app/addChatListMsg', temp)
        const content = this.content
        this.content = ''
        this.insertAtArr = []
        if (this.groupState === 'delGroupMember') { // 被移出群，不得发送消息
          return
        }
        if (_.isUndefined(this.selectMember.isEncryptGroup)) {
          sendSingleChatText(content, roomId, this.selectMember.id + '', requestId)
        } else {
          if (insertAtArr.length > 0) {
            sendGroupChatAt(content, insertAtArr, roomId, requestId)
          } else {
            sendGroupChatText(content, roomId, requestId)
          }
        }
      }
    },
    lineFeed () {
      this.content += '\n'
    },

    /** 将选择的Emoji加入文本 */
    onSelectEmoji (dataEmoji) {
      const str = dataEmoji.emoji
      this.content += str.replace(/(^\s*)|(\s*$)/g, '')
      this.hideDialogEmoji()
    },

    // 拉取历史消息
    async getHistoryList () {
      if (this.$data.historyMsgLoadComplete || this.$data.getHistoryMsgLoading) return
      this.$data.getHistoryMsgLoading = true
      // roomId=884446733008896127&lastMsgId=&pageSize=10
      const pageSize = 20

      let res

      if (this.isGroup) {
        res = await getGroupHistoryList({
          roomId: this.roomId,
          lastMsgId: this.selectChatList.length > 0 ? this.selectChatList[0].messageId : 0,
          pageSize: pageSize
        })
      } else {
        res = await GetSingleHistoryList({
          roomId: this.roomId,
          lastMsgId: this.selectChatList.length > 0 ? this.selectChatList[0].messageId : 0,
          pageSize: pageSize
        })
      }

      if (res.status === 200) {
        // 历史消息禁止滚动

        if (this.selectChatList.length > 9) {
          this.$data.disableScroll = true
        }

        this.$store.commit('app/ADD_HISTORY_MSG', {
          roomId: this.roomId,
          msgList: res.data.rows.reverse()
        })

        if (res.data.rows.length < pageSize) {
          this.$data.historyMsgLoadComplete = true
        }
      }
      this.$data.getHistoryMsgLoading = false
    }
  },
  beforeDestroy () {
    document.onkeydown = undefined
  }
}
</script>

<style lang="scss">
.chat-panel {
  #imgupload,
  #fileupload,
  #videoupload {
    display: none;
  }
  border-left: 1px solid #eee;
  &__item {
    height: 100%;
    display: flex;
    align-items: center;
  }
  &__edit {
    height: 133px;
    position: relative;
    &__title {
      height: 22px;
      padding: 10px 15px;
      user-select: none;
      display: flex;
      align-items: center;
      img {
        cursor: pointer;
        width: 20px;
        height: 20px;
        margin-right: 20px;
      }
      i {
        margin-right: 20px;
      }
    }
  }
  &__edit-disable {
    height: 133px;
    display: flex;
    align-items: center;
    justify-content: center;
  }
  .el-textarea__inner {
    height: 91px !important;
    border-bottom-right-radius: 9px !important;
    border: 1px solid white !important;
    &:focus {
      outline-color: white !important;
    }
  }
  &__list {
    background: rgba(255, 255, 255, 1);
    box-shadow: 0px 2px 10px 0px rgba(0, 0, 0, 0.1);
    border-radius: 6px;
    width: 200px;
    height: 200px;
    position: absolute;
    left: 15px;
    z-index: 9;
    bottom: 90px;
    overflow-y: scroll;
    li {
      margin: 10px;
    }
    .mention-name {
      font-size: 14px;
      font-family: Source Han Sans CN;
      font-weight: 400;
      color: rgba(84, 208, 172, 1);
      cursor: pointer;
    }
    .atwho-cur {
      background: #eeeeee;
    }
    .img-style {
      width: 20px;
      height: 20px;
      border-radius: 50%;
      display: inline-block;
      vertical-align: middle;
    }
    .img-default {
      background: rgba(217, 214, 214, 1);
    }
    .name {
      font-size: 14px;
      font-family: Source Han Sans CN;
      font-weight: 400;
      color: rgba(0, 0, 0, 1);
      margin-left: 10px;
    }
  }
  &__title {
    height: 51px;
    border-bottom: 1px solid #eee;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 15px;
    span.title {
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      max-width: 480px;
      font-weight: 600;
      font-size: 18px;
    }
    &__group {
      i {
        font-size: 20px;
        width: 36px;
        height: 36px;
        border-radius: 50px;
        background-color: #3478f5;
        color: white;
        cursor: pointer;
        display: flex;
        justify-content: center;
        align-items: center;
      }
    }
  }
  &__content {
    height: 423px;
    padding: 7px 15px;
    border-bottom: 1px solid #eee;
    overflow-y: auto;
  }

  .load-more-msg {
    text-align: center;
    font-size: 14px;
    padding: 4px;
    color: #666;
    background-color: #efefef;
    border-radius: 20px;
    cursor: pointer;
    user-select: none;
    &:hover {
      background-color: #f2f2f2;
      color: #888;
    }
  }

  .emoji {
    position: relative;
    &__body {
      position: absolute;
      top: -464px;
      left: -15px;
    }
  }
  .icon {
    font-size: 23px;
    margin-left: 5px;
    cursor: pointer;
    margin-top: 1px;
  }
  // .box-chat-list {
  //   // position: relative;
  //   // min-height: 70px;
  //   margin-bottom: 10px;
  //     .recall-style {
  //     // position: absolute;
  //     // left:40%;
  //     // top: 23%;
  //     display: flex;
  //     align-items: center;
  //     justify-content: center;
  //     font-size:14px;
  //     font-family:Source Han Sans CN;
  //     font-weight:400;
  //     color:rgba(153,153,153,1);
  //     .recall-name {
  //       color: #508AFF;
  //     }
  //   }
  // }
}
</style>
